package com.ruicar.afs.cloud.filecenter.component;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruicar.afs.cloud.filecenter.config.FileConfigCache;
import com.ruicar.afs.cloud.filecenter.dto.AfsFileProcessor;
import com.ruicar.afs.cloud.filecenter.entity.AfsFileStoreConfig;
import com.ruicar.afs.cloud.filecenter.enums.FileAllowEnum;
import com.ruicar.afs.cloud.filecenter.enums.FileProcessorType;
import com.ruicar.afs.cloud.filecenter.mapper.AfsFileStoreConfigMapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * FileCacheInitComponent
 * <p>Description: </p>
 *
 * @author Fzero
 * @version 1.0
 * @date create on 2020-05-29 14:54:08
 * @since 1.0
 */
@Component
@Slf4j
@AllArgsConstructor
public class FileCacheInitComponent implements ApplicationListener<ApplicationReadyEvent> {
    /**
     * Afs file store config mapper
     * <p>Description: </p>
     */
    private final AfsFileStoreConfigMapper afsFileStoreConfigMapper;

    /**
     * On application event *
     *
     * @param event event
     */
    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        // 拒绝上传文件类型和文件签名
        afsFileStoreConfigMapper
                .selectList(Wrappers.<AfsFileStoreConfig>lambdaQuery().eq(AfsFileStoreConfig::getAllowed, FileAllowEnum.DISABLE))
                .stream()
                .forEach(afsFileStoreConfig -> {
                    FileConfigCache.ALLOW_FILE_SIZE.put(afsFileStoreConfig.getConfigType().toUpperCase(),0L);
                    FileConfigCache.BLACK_FILE_TYPE.add(afsFileStoreConfig.getConfigType().toUpperCase());
                    FileConfigCache.BLACK_FILE_SIGNATURE.addAll(Arrays.stream(afsFileStoreConfig.getSignature().split(",")).collect(Collectors.toList()));
                });
        // 允许上传文件大小
        afsFileStoreConfigMapper.
                selectList(Wrappers.<AfsFileStoreConfig>lambdaQuery().eq(AfsFileStoreConfig::getAllowed,FileAllowEnum.ALLOW))
                .stream().forEach(afsFileStoreConfig -> {
            FileConfigCache.ALLOW_FILE_SIZE.put(afsFileStoreConfig.getConfigType(),afsFileStoreConfig.getMaxSize().longValue());
        });
        List<AfsFileProcessor> afsFileProcessorList = afsFileStoreConfigMapper.listProcessor();
        afsFileProcessorList
                .stream()
                .filter(afsFileProcessor -> afsFileProcessor.getFileType().equals("*"))
                .forEach(afsFileProcessor -> {
                    if(afsFileProcessor.getProcessorType()== FileProcessorType.PRE){
                        FileConfigCache.GLOBAL_PRE_FILE_PROCESSOR
                                .add(getProcess(afsFileProcessor.getRegisterId(),event.getApplicationContext()));
                    }else{
                        FileConfigCache.GLOBAL_POST_FILE_PROCESSOR
                                .add(getProcess(afsFileProcessor.getRegisterId(),event.getApplicationContext()));
                    }
                });

        FileConfigCache.GLOBAL_PRE_FILE_PROCESSOR.sort(Comparator.comparingInt(com.ruicar.afs.cloud.filecenter.service.AfsFileProcessor::getOrder));
        FileConfigCache.GLOBAL_POST_FILE_PROCESSOR.sort(Comparator.comparingInt(com.ruicar.afs.cloud.filecenter.service.AfsFileProcessor::getOrder));
        afsFileProcessorList
                .stream()
                .filter(afsFileProcessor -> !afsFileProcessor.getFileType().equals("*"))
                .forEach(afsFileProcessor -> {
                    if(afsFileProcessor.getProcessorType()== FileProcessorType.PRE){
                        if(!FileConfigCache.FILE_PRE_PROCESSOR.containsKey(afsFileProcessor.getFileType().toUpperCase())){
                            FileConfigCache.FILE_PRE_PROCESSOR.put(afsFileProcessor.getFileType().toUpperCase(),new ArrayList<>());
                        }
                        FileConfigCache.FILE_PRE_PROCESSOR.get(afsFileProcessor.getFileType().toUpperCase())
                                .add(getProcess(afsFileProcessor.getRegisterId(),event.getApplicationContext()));
                    }else{
                        if(!FileConfigCache.FILE_POST_PROCESSOR.containsKey(afsFileProcessor.getFileType().toUpperCase())){
                            FileConfigCache.FILE_POST_PROCESSOR.put(afsFileProcessor.getFileType().toUpperCase(),new ArrayList<>());
                        }
                        FileConfigCache.FILE_POST_PROCESSOR.get(afsFileProcessor.getFileType().toUpperCase())
                                .add(getProcess(afsFileProcessor.getRegisterId(),event.getApplicationContext()));
                    }

                });
        FileConfigCache.FILE_PRE_PROCESSOR
                .values()
                .stream()
                .forEach(list->{
                    list.sort(Comparator.comparingInt(com.ruicar.afs.cloud.filecenter.service.AfsFileProcessor::getOrder));
                });
        FileConfigCache.FILE_POST_PROCESSOR
                .values()
                .stream()
                .forEach(list->{
                    list.sort(Comparator.comparingInt(com.ruicar.afs.cloud.filecenter.service.AfsFileProcessor::getOrder));
                });
    }

    /**
     * Get process com . ruicar . afs . cloud . filecenter . service . afs file processor
     * <p>Description: </p>
     *
     * @param registerId         register id
     * @param applicationContext application context
     * @return the com . ruicar . afs . cloud . filecenter . service . afs file processor
     */
    private com.ruicar.afs.cloud.filecenter.service.AfsFileProcessor getProcess(String registerId, ApplicationContext applicationContext){
        return applicationContext
                .getBeansOfType(com.ruicar.afs.cloud.filecenter.service.AfsFileProcessor.class)
                .values()
                .stream()
                .filter(processor->processor.registerId().equals(registerId))
                .findFirst()
                .orElse(com.ruicar.afs.cloud.filecenter.service.AfsFileProcessor.DEFAULT_PROCESS);

    }
}
